import { FC, useState, useEffect, useRef } from 'react'
import { Slider, Select } from 'antd'
import { PlayCircleOutlined, PauseOutlined, StepBackwardOutlined, StepForwardOutlined } from '@ant-design/icons'
// stores
import { appShallowEqual, useAppSelector, useAppDispatch } from '@/stores'
import { changePlay, changeSon } from '@/stores/modules/music'
// selfHooks
import { useSetState } from '@/hooks/index'
//  自定义方法
import { formatMilliseconds } from '@/untils/index'
// less
import './footer.less'
// ts
import { SongType } from '@/untils/musicType'
const MusicListFooter: FC = () => {
  const dispatch = useAppDispatch()
  const { play, songId, musicList } = useAppSelector(
    (state) => ({
      play: state.musicReducer.play,
      songId: state.musicReducer.songId,
      musicList: state.musicReducer.musicList
    }),
    appShallowEqual
  )
  const initSong = () => ({
    id: '',
    title: '',
    url: '',
    sizeBytes: 0,
    durationMilliseconds: 0,
    singerName: '',
    album: ''
  })
  const [song, setSong] = useState<SongType>(initSong())
  const [state, setState] = useSetState<any>({
    rate: 1,
    pitch: 1000,
    currentTime: 0,
    volume: 100,
    timbre: null
  })
  // 保存音频上下文
  const audioContextRef = useRef<AudioContext>()
  // 保存解码音频数据
  const audioBufferRef = useRef<AudioBuffer>()
  // 保存音频节点，用于播放音频数据
  const audioBufferSource = useRef<AudioBufferSourceNode>()
  // 保存增益节点
  const gainNodeRef = useRef<GainNode>()
  // 保存滤波器节点
  const filterNodeRef = useRef<BiquadFilterNode>()
  const first = useRef<boolean>(true)
  useEffect(() => {
    const song = musicList?.find((item) => item.id === songId)
    pauseAudio()
    setState({
      currentTime: 0
    })
    if (song?.url) {
      setSong(song)
    }
  }, [songId])
  useEffect(() => {
    if (!first.current) {
      dispatch(changePlay(true))
      playMusic()
    }
    if (song.id) first.current = false
  }, [song])
  // 播放音频
  let palyStartTime = useRef<number>(+new Date())
  const timer = useRef<any>(null)
  // 设置进度更新
  const updateProgress = (source: AudioBufferSourceNode) => {
    const currentTime = state.currentTime
    const now = +new Date()
    if (source) {
      setState({
        currentTime: currentTime + now - palyStartTime.current
      })
    }
    timer.current = setTimeout(() => {
      updateProgress(source)
    }, 60)
    if (currentTime + now - palyStartTime.current > song.durationMilliseconds) {
      nextMusic()
    }
    // 音频播放结束
    source.onended = () => {}
  }
  const playMusic = (currentTime?: number) => {
    pauseAudio()
    audioContextRef.current = new window.AudioContext()
    // 创建一个音频节点audioBufferSource，用于播放已经解码的音频数据（AudioBuffer）
    audioBufferSource.current = audioContextRef.current.createBufferSource()
    // 保存增益节点
    gainNodeRef.current = audioContextRef.current.createGain()
    // 保存滤波器节点
    filterNodeRef.current = audioContextRef.current.createBiquadFilter()
    fetch(song.url)
      .then((response) => {
        return response.arrayBuffer()
      })
      .then((arrayBuffer) => {
        return (audioContextRef.current as AudioContext).decodeAudioData(arrayBuffer)
      })
      .then((audioBuffer) => {
        if (!audioBufferSource.current || !gainNodeRef.current || !filterNodeRef.current) return
        audioBufferRef.current = audioBuffer
        audioBufferSource.current.buffer = audioBuffer
        audioBufferSource.current.connect(gainNodeRef.current)
        gainNodeRef.current.connect((audioContextRef.current as AudioContext).destination)
        const time = currentTime || state.currentTime
        audioBufferSource.current.start(0, time / 1000)
        palyStartTime.current = +new Date()
        updateProgress(audioBufferSource.current)
      })
      .catch((error) => {
        console.error('Error loading or decoding audio:', error)
      })
  }
  // 暂停音频
  const pauseAudio = () => {
    try {
      if (audioBufferSource.current) {
        audioBufferSource.current?.stop?.()
        audioBufferSource.current?.disconnect?.()
      }
      timer.current && clearInterval(timer.current)
    } catch (error) {}
  }
  useEffect(() => {
    play ? playMusic() : pauseAudio()
  }, [play])
  const onAfterChange = (value: number) => {
    dispatch(changePlay(false))
    setState({
      currentTime: value
    })
    timer.current && clearInterval(timer.current)
    setTimeout(() => {
      dispatch(changePlay(true))
    })
  }
  const onChangePlay = () => {
    dispatch(changePlay(!play))
  }
  const nextMusic = () => {
    let index = musicList.findIndex((item) => item.id === songId)
    if (index === musicList.length - 1) index = 0
    else index = index + 1
    dispatch(changeSon(musicList?.[index]?.id))
  }
  const perMusic = () => {
    let index = musicList.findIndex((item) => item.id === songId)
    if (index === 0) index = musicList.length - 1
    else index = index - 1
    dispatch(changeSon(musicList?.[index]?.id))
  }
  // 调整音速
  const changeRate = (value: number) => {
    if (!audioBufferSource.current) return
    audioBufferSource.current.playbackRate.value = value
  }
  // 调整音色
  const changeTimbre = (value: BiquadFilterType) => {
    if (!filterNodeRef.current || !audioBufferSource.current || !audioContextRef.current) return
    if (value) {
      filterNodeRef.current.type = value
      audioBufferSource.current.disconnect()
      audioBufferSource.current.connect(filterNodeRef.current)
      filterNodeRef.current.connect(audioContextRef.current.destination)
    } else {
      audioBufferSource.current.disconnect()
      audioBufferSource.current.connect(audioContextRef.current.destination)
    }
  }
  return (
    <div className="music-list-footer">
      <div className="music-list-footer-info">
        <img src="https://wx4.sinaimg.cn/mw690/b3e366e1gy1hr8fashq9qj20tw0tstbc.jpg" alt="" />
        <div className="song-info">
          <div className="song-info-title">{song.title}</div>
          <div>{song.singerName}</div>
        </div>
      </div>
      <div className="music-list-footer-control">
        <StepBackwardOutlined onClick={perMusic} />
        {play ? <PauseOutlined onClick={onChangePlay} /> : <PlayCircleOutlined onClick={onChangePlay} />}
        <StepForwardOutlined onClick={nextMusic} />
      </div>
      <div className="music-list-footer-progress">
        <div>{formatMilliseconds(state.currentTime)}</div>
        <Slider
          onAfterChange={onAfterChange}
          tooltip={{ formatter: null }}
          value={state.currentTime}
          max={song.durationMilliseconds}
          min={0}
        />
        <div>{formatMilliseconds(song.durationMilliseconds)}</div>
      </div>
      <div className="music-list-footer-volume">
        <img src={require('@/assets/images/musicList/volume.svg').default} alt="" />
        <Slider
          onChange={(value) => {
            if (!gainNodeRef.current) return
            gainNodeRef.current.gain.value = value
            setState({ volume: value })
          }}
          tooltip={{ formatter: null }}
          value={state.volume}
          step={0.1}
          max={1}
          min={0}
        />
        <div className="music-list-footer-volume-style">
          音速：
          <Slider
            step={0.1}
            min={0}
            max={2}
            value={state.rate}
            onChange={(value) => {
              setState({
                rate: value
              })
              changeRate(value)
            }}
          ></Slider>
          音色：
          <Select
            value={state.timbre}
            onChange={(value: BiquadFilterType) => {
              setState({
                timbre: value
              })
              changeTimbre(value)
            }}
            options={[
              {
                value: null,
                label: '正常'
              },
              {
                value: 'highpass',
                label: '高音'
              },
              {
                value: 'lowpass',
                label: '低音'
              }
            ]}
          ></Select>
        </div>
      </div>
    </div>
  )
}
export default MusicListFooter
